/**
 * 
 */
package com.yishuki.bluewhale.db.access;

import java.util.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.yishuki.bluewhale.ErrorCodeMsg;
import com.yishuki.bluewhale.YishukiException;
import com.yishuki.bluewhale.db.entity.User;

import name.yzhu.common.util.Security;
import name.yzhu.database.DataBaseException;
import name.yzhu.database.IDbUtil;

/**
 * @author yhzhu
 *
 */
public class UserOpr extends AbstractDBOpr{
	private static final Log LOG = LogFactory.getLog(UserOpr.class);
	private Date oprTime = new Date();
	
	public UserOpr(IDbUtil db) {
		super(db);
	}
	/**
	 * check if the user name and password are valid and don't commit any transf
	 * @param name
	 * @param password
	 * @return
	 * @throws YishukiException
	 */
	public User checkUser(String name, String password) throws YishukiException{
		return checkUser(name, password, false);
	}
	/**
	 * check if the user name and password are valid 
	 * @param name
	 * @param password
	 * @param isCommitted
	 * @return
	 * @throws YishukiException
	 */
	public User checkUser(String name, String password, boolean isCommitted) throws YishukiException{
		String hql = "from User where name = ? and password = ?";
		try {
			List<Object> list = db.queryListForHQL(hql, 0, 1, name, Security.EncodeByMD5(password));
			if (list == null){
				throw new YishukiException(ErrorCodeMsg.DB_ERROR, ErrorCodeMsg.getErrMsg(ErrorCodeMsg.DB_ERROR));
			}
			
			if (list.size() == 0){
				throw new YishukiException(ErrorCodeMsg.LOGIN_FAILED);
			}
			User u = (User) list.get(0);
			LOG.debug(u);
			if (u.getLockedTime() != null)
				throw new YishukiException(ErrorCodeMsg.USER_LOCKED);
			u.setLastVisitTime(this.oprTime);
			db.merge(u);
			if (isCommitted)
				db.flush();
			return u;
		} catch (DataBaseException e) {
			if (LOG.isDebugEnabled())
				LOG.error(e.getMessage(), e);
			throw new YishukiException(ErrorCodeMsg.DB_ERROR, e);
		}
	}
	/**
	 * lock a user  without commit
	 * @param u
	 * @throws YishukiException
	 */
	public void lockUser(User u) throws YishukiException{
		lockUser(u, false);
	}
	/**
	 * lock a user
	 * @param u
	 * @param isCommit
	 * @throws YishukiException
	 */
	public void lockUser(final User u, boolean isCommit) throws YishukiException{
		try {
			u.setLockedTime(this.oprTime);
			db.merge(u);
			if (isCommit)
				db.flush();
		} catch (DataBaseException e) {
			if (LOG.isDebugEnabled())
				LOG.error(e.getMessage(), e);
			throw new YishukiException(ErrorCodeMsg.DB_ERROR, e);
		}
	}
	/**
	 * unlock user without commit
	 * @param u
	 * @throws YishukiException
	 */
	public void unlockUser(final User u) throws YishukiException{
		unlockUser(u, false);
	}
	/**
	 * unlock a user 
	 * @param u
	 * @param isCommit
	 * @throws YishukiException
	 */
	public void unlockUser(final User u, boolean isCommit) throws YishukiException{
		try {
			u.setLockedTime(null);
			db.merge(u);
			if (isCommit)
				db.flush();
		} catch (DataBaseException e) {
			if (LOG.isDebugEnabled())
				LOG.error(e.getMessage(), e);
			throw new YishukiException(ErrorCodeMsg.DB_ERROR, e);
		}
	}
	/**
	 * change password without commit
	 * @param u
	 * @param password
	 * @throws YishukiException
	 */
	public void changePassword(final User u, String password) throws YishukiException{
		changePassword(u, password, false);
	}
	/**
	 * change password
	 * @param u
	 * @param password
	 * @param isCommit
	 * @throws YishukiException
	 */
	public void changePassword(final User u, String password, boolean isCommit) throws YishukiException{
		u.setPassword(Security.EncodeByMD5(password));
		try {
			db.merge(u);
			if (isCommit)
				db.flush();
		} catch (DataBaseException e) {
			if (LOG.isDebugEnabled())
				LOG.error(e.getMessage(), e);
			throw new YishukiException(ErrorCodeMsg.DB_ERROR, e);
		}
	}
	/**
	 * add a new user without commit
	 * @param u
	 * @throws YishukiException
	 */
	public void addUser(final User u) throws YishukiException{
		addUser(u, false);
	}
	/**
	 * add a new user
	 * @param u
	 * @param isCommit
	 * @throws YishukiException
	 */
	public void addUser(final User u, boolean isCommit) throws YishukiException{
		u.setSignUpTime(this.oprTime);
		u.setLastVisitTime(this.oprTime);
		u.setPassword(Security.EncodeByMD5(u.getPassword()));
		if (!u.checkRequiredFields()){
			LOG.debug(u);
			throw new YishukiException(ErrorCodeMsg.MISS_REQIRED_FIELD);
		}
		try {
			db.save(u);
			if (isCommit)
				db.flush();
		} catch (DataBaseException e) {
			if (LOG.isDebugEnabled())
				LOG.error(e.getMessage(), e);
			throw new YishukiException(ErrorCodeMsg.DB_ERROR, e);
		}
	}
	/**
	 * update user without commit
	 * @param oldU
	 * @param newUser
	 * @throws YishukiException
	 */
	public void updateUser(User oldU, User newUser) throws YishukiException{
		updateUser(oldU, newUser, false);
	}
	/**
	 * update user <br>
	 * <b>Node:</b> the password of the new user couldn't be encoded
	 * @param oldU
	 * @param newUser
	 * @param isCommit
	 * @throws YishukiException
	 */
	public void updateUser(User oldU, User newUser, boolean isCommit) throws YishukiException{
		oldU.setEmail(newUser.getEmail());
		oldU.setName(newUser.getName());
		oldU.setPassword(Security.EncodeByMD5(newUser.getPassword()));
		oldU.setPermissionId(newUser.getPermissionId());
		if (!oldU.checkRequiredFields()){
			LOG.debug(oldU);
			throw new YishukiException(ErrorCodeMsg.MISS_REQIRED_FIELD);
		}
		try {
			db.merge(oldU);
			if (isCommit)
				db.flush();
		} catch (DataBaseException e) {
			if (LOG.isDebugEnabled())
				LOG.error(e.getMessage(), e);
			throw new YishukiException(ErrorCodeMsg.DB_ERROR, e);
		}
	}
	/**
	 * delete user without commit
	 * @param u
	 * @throws YishukiException
	 */
	public void deleteUser(User u) throws YishukiException{
		deleteUser(u, false);
	}
	/**
	 * delete a user
	 * @param u
	 * @param isCommit
	 * @throws YishukiException
	 */
	public void deleteUser(User u, boolean isCommit) throws YishukiException{
		try {
			db.Delete(u);
			if (isCommit)
				db.flush();
		} catch (DataBaseException e) {
			if (LOG.isDebugEnabled())
				LOG.error(e.getMessage(), e);
			throw new YishukiException(ErrorCodeMsg.DB_ERROR, e);
		}
	}
	/**
	 * delete user by name without commit
	 * @param name
	 * @throws YishukiException
	 */
	public void deleteUser(String name) throws YishukiException{
		deleteUser(name, false);
	}
	/**
	 * delete user by name
	 * @param name
	 * @param isCommit
	 * @throws YishukiException
	 */
	public void deleteUser(String name, boolean isCommit) throws YishukiException{
		String hql = "Delete User where name=?";
		try {
			db.saveOrUpdateOrDelForHQL(hql, name);
			if (isCommit)
				db.flush();
		} catch (DataBaseException e) {
			if (LOG.isDebugEnabled())
				LOG.error(e.getMessage(), e);
			throw new YishukiException(ErrorCodeMsg.DB_ERROR, e);
		}
	}
	/**
	 * set current time 
	 * @param oprTime
	 */
	public void setOprTime(Date oprTime) {
		this.oprTime = oprTime;
	}
}
